图像处理20211215

73次阅读
没有评论

共计 4500 个字符,预计需要花费 12 分钟才能阅读完成。

提醒:本文最后更新于 2024-08-29 15:10,文中所关联的信息可能已发生改变,请知悉!

上周问题

图像处理 20211215

每个 3 * 3 区域内的单个噪声点几乎完全消除,但是在像素修改上存在不合理的情况,比如在图像的明显分界线上,像素互相侵蚀。

出现这样情况的原因如下图,在不考虑中心点(黄色)的情况下,设红色像素点是噪声,那么这个 3 * 3 矩阵,满足 1:7 的划分状态,我们肯定能定位出红色的噪声点,但是在修改噪声的时候,会取蓝色区域内最接近于红色值的像素值来赋给红色像素点。

由于降噪算法的核心就是根据原有的合理像素值猜测出噪声值本来的样子,那么在不考虑四个边界的像素点情况下,每个像素点都有与它联系最紧密的 8 邻域像素,我称它们为最佳关联点。

当猜测噪声点的原值的时候,最佳关联点对它的影响越大,则猜的越准,那么刚才的修改方法就不太合适:

  • 如图所示,该修改方法使用的红色像素点的最佳关联点只有四个,还有三个非最佳关联点,如果这个红色点在四个角上的话,那么,会使用到的最佳关联点只有两个,非最佳关联点有五个
  • 由于该噪声定位的方法与以前先定位加权,再修改的方式不同,所以我们不能保证蓝色像素点部分没有噪声,只是因为红色的噪声更突出,所以分出来 1:7 的状态,那么在修改的时候,不可避免的会使用到比非最佳关联点还要不合理的噪声点

图像处理 20211215

改进代码

# python 3.8
# utf-8
# follow 20211124 report

import cv2 as cv
import numpy as np

# 二维数组映射到一维
def _2d_2_1d(x, y):
    if x == 0 and y == 0:
        return int(0)
    elif x == 0 and y == 1:
        return int(1)
    elif x == 0 and y == 2:
        return int(2)
    elif x == 1 and y == 2:
        return int(3)
    elif x == 2 and y == 2:
        return int(4)
    elif x == 2 and y == 1:
        return int(5)
    elif x == 2 and y == 0:
        return int(6)
    elif x == 1 and y == 0:
        return int(7)
    elif x == 1 and y == 1:
        return int(8)

def _1d_2_2d(x):
    if x == 0:
        return 0, 0
    elif x == 1:
        return 0, 1
    elif x == 2:
        return 0, 2
    elif x == 3:
        return 1, 2
    elif x == 4:
        return 2, 2
    elif x == 5:
        return 2, 1
    elif x == 6:
        return 2, 0
    elif x == 7:
        return 1, 0

def division(_8):
    result = [0] * 8
    p1 = [_8[0][0], _8[0][1], _8[0][2], _8[1][2], _8[2][2], _8[2][1], _8[2][0],
          _8[1][0]]
    p = sorted(p1)
    q = [abs(int(p[0]) - int(p[1])), abs(int(p[1]) - int(p[2])), abs(int(p[2]) - int(p[3])), abs(int(p[3]) - int(p[4])),
         abs(int(p[4]) - int(p[5])), abs(int(p[5]) - int(p[6])), abs(int(p[6]) - int(p[7]))]
    # 判断区分度
    if max(q) < 10:
        return result, False
    max_index = q.index(max(q))
    for i in range(0, max_index + 1):
        for j in range(len(q)):
            if p1[j] == p[i]:
                result[j] = 1
    for i in range(8):
        if result[i] != 1:
            result[i] = 2
    return result, True

def find_best(a, x, y, flag):
    p = a[x][y]
    neighborhood = []
    if flag[x - 1][y - 1] == 0:
        neighborhood.append(a[x - 1][y - 1])
    if flag[x - 1][y]:
        neighborhood.append(a[x - 1][y])
    if flag[x - 1][y + 1]:
        neighborhood.append(a[x - 1][y + 1])
    if flag[x][y + 1]:
        neighborhood.append(a[x][y + 1])
    if flag[x + 1][y + 1]:
        neighborhood.append(a[x + 1][y + 1])
    if flag[x + 1][y]:
        neighborhood.append(a[x + 1][y])
    if flag[x + 1][y - 1]:
        neighborhood.append(a[x + 1][y - 1])
    if flag[x][y - 1]:
        neighborhood.append(a[x][y - 1])

    d = []
    for i in range(len(neighborhood)):
        d.append(abs(int(neighborhood[i]) - int(p)))
    if len(d) == 0:
        return p
    min_index = d.index(min(d))

    return neighborhood[min_index]

def denoise_1_7(channel, flag, k):
    """
    :param channel: 待检测通道
    :param flag: 噪声标记
    :param k: 多尺度指数
    :return: 被找到的噪声个数
    """
    x, y = channel.shape

    flag0 = np.zeros((x, y))

    sub_flag = 0

    for i in range(1, x - 1):
        for j in range(1, y - 1):
            # 取出九宫格
            a = [[0] * 3 for ix in range(3)]
            for i0 in range(3):
                for j0 in range(3):
                    a[i0][j0] = channel[i - 1 + i0][j - 1 + j0]

            # 划分区域
            div, div_flag = division(a)

            if not div_flag:
                continue

            cnt = 0
            for i0 in range(8):
                if div[i0] == 1:
                    cnt += 1

            if cnt == 1:
                for i0 in range(8):
                    if div[i0] == 1:
                        x0, y0 = _1d_2_2d(i0)
                        if flag[i - 1 + x0][j - 1 + y0] == 1 and flag0[i - 1 + x0][j - 1 + y0] == 0:
                            sub_flag += 1
                        flag0[i - 1 + x0][j - 1 + y0] = 1
                        # channel[i - 1 + x0][j - 1 + y0] = find_best(a, x0, y0)

            elif cnt == 7:
                for i0 in range(8):
                    if div[i0] == 2:
                        x0, y0 = _1d_2_2d(i0)
                        if flag[i - 1 + x0][j - 1 + y0] == 1 and flag0[i - 1 + x0][j - 1 + y0] == 0:
                            sub_flag += 1
                        flag0[i - 1 + x0][j - 1 + y0] = 1
                        # channel[i - 1 + x0][j - 1 + y0] = find_best(a, x0, y0)

    for i in range(1, x - 1):
        for j in range(1, y - 1):
            if flag[i][j] == 1:
                channel[i][j] = find_best(channel, i, j, flag0)

    return channel, sub_flag

def denoise(noise, noise_flag, k):
    """
    :param noise: 噪声图像
    :param noise_flag: 噪声标记
    :param k: 多尺度指数
    :return: 修改后的噪声图像,被找到的噪声
    """
    b_noise, g_noise, r_noise = cv.split(noise)

    sub_flag = 0

    b_noise, f = denoise_1_7(b_noise, noise_flag[0], k)
    sub_flag += f
    g_noise, f = denoise_1_7(g_noise, noise_flag[1], k)
    sub_flag += f
    r_noise, f = denoise_1_7(r_noise, noise_flag[2], k)
    sub_flag += f

    new_noise = cv.merge((b_noise, g_noise, r_noise))

    return new_noise, sub_flag

def get_noise_flag(origin, noise):
    """
    :param origin: Mat 原图
    :param noise: Mat 噪声图
    :return: flag 矩阵
    """
    b_origin, g_origin, r_origin = cv.split(origin)
    b_noise, g_noise, r_noise = cv.split(noise)

    row, col = b_origin.shape

    flag = np.zeros((3, row, col))

    cnt_flag = 0

    for i in range(row):
        for j in range(col):
            if b_origin[i][j] != b_noise[i][j]:
                flag[0][i][j] = 1
                cnt_flag += 1
            if g_origin[i][j] != g_noise[i][j]:
                flag[1][i][j] = 1
                cnt_flag += 1
            if r_origin[i][j] != r_noise[i][j]:
                flag[2][i][j] = 1
                cnt_flag += 1
    return flag, cnt_flag

def main(origin, noise, k):
    """
    :param origin: 原始标准图片路径
    :param noise: 噪声图路径
    :param k: 多尺度指数
    :return:
    """
    img_origin = cv.imread(origin, 1)
    img_noise = cv.imread(noise, 1)

    noise_flag, cnt_flag = get_noise_flag(img_origin, img_noise)

    print(' 原噪声个数:', cnt_flag)

    # new_noise, sub_flag = denoise(img_noise, noise_flag, 1)

    # cv.imwrite('new.png', new_noise)

    # print(sub_flag / cnt_flag)

    noises = []
    noises.append(img_noise)
    for i in range(10):
        new, sub_flag = denoise(noises[i], noise_flag, 1)
        noises.append(new)
        print('[' + str(i + 1) + ']', sub_flag / cnt_flag)

    cv.imwrite('new.png', noises[9])

if __name__ == '__main__':
    origin_addr = 'img.png'
    noise_addr = 'img_1.png'
    main(origin_addr, noise_addr, 1)

测试效果

原图:

图像处理 20211215

噪声图:

图像处理 20211215

处理图:

图像处理 20211215

被处理噪声个数占比 60+%

正文完
 0
icvuln
版权声明:本站原创文章,由 icvuln 于2021-12-15发表,共计4500字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)